#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>

using namespace std;
const int ptr_field_size = 32;
// const int pcb_list_size = 128;

/***
指针域向量表
0 --> 池队列指针域
1 --> 总链队列指针域
2 --> 就绪队列指针域
3 --> 等待队列指针域

进程状态向量表
-1 --> 池
3-10  --> 等待
2  --> 就绪
***/

struct pcb_list_node {
  pcb_list_node *next;                  // PCB总指针
  pcb_list_node *_next[ptr_field_size]; //指针域

  /** 调度信息 **/
  string process_name;              //进程名
  int process_id;                   //进程号
  int priority;                     //优先级
  int current_status;               //当前状态
  void *storage_message;            //存储信息
  vector<void *> resource_list;     //资源清单
  vector<pcb_list_node *> children; //子进程指针列表
  vector<int> current_file;         //当前打开文件

  /** 现场信息 **/
  int PSW;                           //程序状态字
  int clock_message;                 //时钟
  int up_boundary_address_register;  //地址上界寄存器
  int low_boundary_address_register; //地址下界寄存器
};

pcb_list_node *HEAD;                // PCB表头指针
pcb_list_node *head[ptr_field_size]; //不同指针域队列头指针
pcb_list_node *tail[ptr_field_size];
pcb_list_node *running_ptr;

void initialize_system() {
  HEAD = new pcb_list_node;

  for (int i = 0; i < ptr_field_size; ++i) { // first
    tail[i] = head[i] = new pcb_list_node;
    tail[i]->_next[i] = nullptr;
  }

  pcb_list_node *pre = HEAD;
  pcb_list_node *pool_pre = head[0];

  for (int i = 0; i < ptr_field_size; ++i) {
    pcb_list_node *cur = new pcb_list_node;
    cur->process_id = i;
    cur->current_status = -1;
    pre->next = cur;
    pool_pre->_next[0] = cur;
    pool_pre = cur;
    pre = cur;
  }

  tail[0] = pool_pre;
  tail[0]->_next[0] = nullptr;
  pre->next = nullptr;
}

//创建原语
void create(const string &pname, int ppri) {
  if (!head[0]->_next[0]) {
    puts("Can't create more processes");
    return;
  }

  pcb_list_node *newed = head[0]->_next[0]; //取池队列头结点的下一个

  head[0]->_next[0] = newed->_next[0];
  newed->_next[1] = nullptr;
  newed->_next[0] = nullptr;
  newed->process_name = pname;
  newed->priority = ppri;
  newed->current_status = 2;
  tail[2]->_next[2] = newed;
  tail[2] = newed;
  tail[2]->_next[2] = nullptr;
  tail[1]->_next[1] = newed;
  tail[1] = newed;
  tail[1]->_next[1] = nullptr;

  if (running_ptr == nullptr) {
    running_ptr = head[2]->_next[2];
  }
}

//撤销
void revocate() {
  pcb_list_node *pre = nullptr;
  pcb_list_node *ptr = head[1];

  while (ptr->_next[1]) {
    if (ptr->_next[1] == running_ptr) {
      pre = ptr;
      break;
    }
    ptr = ptr->_next[1];
  }

  if (pre == nullptr) {
    puts("error, no running process!");
    return;
  }

  pcb_list_node *newed = running_ptr;
  tail[0]->_next[0] = newed;
  pre->_next[1] = newed->_next[1];
  newed->_next[1] = nullptr;
  newed->_next[0] = nullptr;
  newed->current_status = -1;
  tail[0] = newed;
  tail[0]->_next[0] = nullptr;
  head[2]->_next[2] = head[2]->_next[2]->_next[2];
  running_ptr->process_name.clear();
  running_ptr = head[2]->_next[2];
}

//挂起
void suspend(int reason) {
  pcb_list_node *newed = running_ptr;
  newed->current_status = reason;
  tail[reason]->_next[reason] = newed;
  tail[reason] = newed;
  tail[reason]->_next[reason] = nullptr;
  head[2]->_next[2] = head[2]->_next[2]->_next[2];
  running_ptr = head[2]->_next[2]; // second
}

//激活
void activate(int reason) {
  pcb_list_node *newed = head[reason]->_next[reason];
  newed->current_status = 2;
  tail[2]->_next[2] = newed;
  tail[2] = newed;
  tail[2]->_next[2] = nullptr;
  head[reason]->_next[reason] = newed->_next[reason];
}

//时间片到
void run_out_of_time_slice() {
  if (running_ptr == nullptr) {
    return;
  }

  pcb_list_node *newed = running_ptr;

  head[2]->_next[2] = head[2]->_next[2]->_next[2];
  tail[2]->_next[2] = newed;
  tail[2] = newed;
  tail[2]->_next[2] = nullptr;
  running_ptr = head[2]->_next[2];
}

void show() {
  if (running_ptr != nullptr) {
    printf("running process is %s\n", running_ptr->process_name.c_str());
  }

  printf("now show the PCB pool：\n");
  pcb_list_node *newed = head[0]->_next[0];
  while (newed) {
    printf("(PCB name:%s,  id:%d) \n", (newed->process_name).c_str(),
           newed->process_id);
    newed = newed->_next[0];
  }

  printf("now show the PCB main chain：\n");
  newed = head[1]->_next[1];
  while (newed) {
    printf("(PCB name:%s,  id:%d) \n", (newed->process_name).c_str(),
           newed->process_id);
    newed = newed->_next[1];
  }

  printf("now show the ready chain：\n");
  newed = head[2]->_next[2];
  while (newed) {
    printf("(PCB name:%s,  id:%d) \n", (newed->process_name).c_str(),
           newed->process_id);
    newed = newed->_next[2];
  }

  for (int i = 3; i <= 10; i++) {
    printf("now show the waiting pool for the %d reason：\n", i);
    pcb_list_node *newed = head[i]->_next[i];
    while (newed) {
      printf("(PCB name:%s,  id:%d) \n", (newed->process_name).c_str(),
             newed->process_id);
      newed = newed->_next[i];
    }
  }
}

int main() {
  char opt[128];
  char arg_name[128];
  int arg_int;

  initialize_system();

  while (true) {
    printf("    command list\n");
    printf("1.create   <process name> <process priority>\n");
    printf("2.revocate\n");
    printf("3.suspend  <reason>\n");
    printf("4.activate <reason>\n");
    printf("5.rts\n");
    printf("6.show\n");

    scanf("%s", opt);

    if (strcmp(opt, "create") == 0) {
      scanf("%s%d", arg_name, &arg_int);
      create(arg_name, arg_int);
    } else if (strcmp(opt, "revocate") == 0) {
      revocate();
    } else if (strcmp(opt, "suspend") == 0) {
      scanf("%d", &arg_int);
      suspend(arg_int);
    } else if (strcmp(opt, "activate") == 0) {
      scanf("%d", &arg_int);
      activate(arg_int);
    } else if (strcmp(opt, "rts") == 0) {
      run_out_of_time_slice();
    } else if (strcmp(opt, "show") == 0) {
      show();
    } else {
      assert(0);
    }
    // system("cls");
  }
  return 0;
}
